import ctypes
import json
import os.path
import re
import tempfile
import time
from subprocess import Popen

from PySide6.QtCore import QRegularExpression, QCoreApplication, QTimer
from PySide6.QtGui import QIcon, QFont

from ControllerThread import ControllerThread
from PalTools import Ui_PalTools
from PySide6.QtWidgets import (QMainWindow, QApplication, QLabel, QMessageBox,
                               QComboBox, QLineEdit, QFileDialog, QPushButton)
import sys

from ServiceController import ServiceController, build_config, build_result


def is_admin():
    if sys.platform.startswith("win"):
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        except:
            return False
    return True


def get_admin():
    if not is_admin():
        from win32con import SW_HIDE
        ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, SW_HIDE)


def get_dir_size(path):
    total_size = 0
    for dirpath, dirnames, filenames in os.walk(path):
        for f in filenames:
            fp = os.path.join(dirpath, f)
            try:
                total_size += os.path.getsize(fp)
            except OSError:
                pass
    return total_size


def enable_button(obj: QPushButton):
    obj.setEnabled(True)


def check_string_type(val: str):
    if re.match(r"^-?\d+$", val):
        return 0
    elif re.match(r"^-?\d+\.\d+$", val):
        return 1
    else:
        return 2


class PalToolsGUI(Ui_PalTools):
    def __init__(self, main_window: QMainWindow):
        super().__init__()
        self.install = None
        self.progress = float()
        self.update_init = True
        self.install_thread = None
        self.update_thread = None
        self.check_thread = None
        self.main_window = main_window
        if not is_admin():
            QMessageBox.information(self.main_window, "提示", "当前无管理员权限，建议使用管理员权限运行！")
        if getattr(sys, "frozen", False):
            base_path = sys._MEIPASS
        else:
            base_path = os.path.dirname(os.path.abspath(__file__))
        self.app_version = 1.65
        self.update_game_thread = None
        self.confirm_box = None
        self.recovery_archive_thread = None
        self.start_thread = None
        self.kill_thread = None
        self.update_config_thread = None
        self.init_thread = None
        self.global_pal_dict = None
        self.data = dict()
        self.log_lines = 0
        self.control_map = dict()
        self.window_icon = os.path.join(base_path, "images", "PalTools.png")
        self.tools_config_path = "PalTools.json"
        self.archive_backup_path = []
        self.only_read_items = ["LogFormatType_label", "AutoSaveSpan_label",
                                "AllowConnectPlatform_label", "ServerReplicatePawnCullDistance_label"]
        self.items_events = []
        self.setupUi(self.main_window)
        self.main_window.setWindowIcon(QIcon(self.window_icon))
        self.config_search.textChanged.connect(self.config_search_func)
        self.steamcmd_path_select.clicked.connect(self.steamcmd_path_select_func)
        self.init_data()
        self.update_backup_items()
        self.flush_archive.clicked.connect(self.update_backup_items)
        self.status_timer = QTimer()
        self.status_timer.setInterval(1000)
        self.status_timer.timeout.connect(self.update_pal_server_status)
        self.status_timer.start()
        self.start_service.clicked.connect(self.start_service_func)
        self.stop_service.clicked.connect(self.kill_service_func)
        self.start_config.clicked.connect(self.update_config_func)
        self.select_archive.setFixedWidth(191)
        self.select_archive.view().setFixedWidth(600)
        with open(os.path.join(base_path, "html", "parameters_details.html"), "r", encoding="utf-8") as f:
            html = f.read().encode("utf-8").decode("utf-8")
            self.pal_parameters_details.setHtml(html)
        self.recovery_archive.clicked.connect(self.recovery_archive_func)
        self.update_game.clicked.connect(self.update_game_func)
        self.check_version.clicked.connect(self.check_update)
        self.check_update()
        self.update_timer = QTimer()
        self.update_timer.setInterval(10)
        self.update_timer.timeout.connect(self.progress_bar_update)
        self.update_timer.start()

    def check_update(self):
        self.check_version.setEnabled(False)
        update = ServiceController(self.steamcmd_path.text())
        update.app_version = self.app_version
        update.exec_func = update.check
        self.check_thread = ControllerThread(update)
        self.check_thread.result.connect(self.download_software)
        self.check_thread.finished.connect(lambda: enable_button(self.check_version))
        self.check_thread.start()

    def download_software(self, is_update):
        if "result" not in is_update["data"].keys():
            QMessageBox.warning(self.main_window, "警告", is_update["msg"])
            return
        if is_update["data"]["result"]:
            reply = self.confirm("有新版本！是否更新软件？")
            if reply == QMessageBox.StandardButton.Yes:
                self.tabWidget.setCurrentWidget(self.tab_3)
                self.update_progress_bar.setFixedHeight(23)
                update_version = ServiceController(self.steamcmd_path.text())
                update_version.new_version = is_update["data"]["new_version"]
                update_version.exec_func = update_version.download
                self.update_thread = ControllerThread(update_version)
                self.update_thread.result.connect(self.add_progress)
                self.update_thread.download_finished.connect(self.install_software)
                self.update_thread.start()
        else:
            if not self.update_init:
                QMessageBox.information(self.main_window, "提示", "已经是最新版本！")
            else:
                self.update_init = False

    def install_software(self, result):
        try:
            if result['code'] == 0:
                exec_path = f"{tempfile.gettempdir()}/PalToolsGUI_Installer.exe"
                Popen(exec_path, creationflags=8)
                QCoreApplication.quit()
            else:
                QMessageBox.warning(self.main_window, "警告", f"下载更新失败！{result['msg']}")
        except WindowsError as e:
            QMessageBox.warning(self.main_window, "警告", f"请使用管理员权限运行此程序！{e}")
        except Exception as e:
            QMessageBox.warning(self.main_window, "警告", f"软件异常！{e}")

    def add_progress(self, progress: dict):
        # print(progress)
        if progress["code"] == 0:
            if "result" in progress["data"].keys():
                self.progress = progress["data"]["result"]

    def progress_bar_update(self):
        self.update_progress_bar.setValue(self.progress)

    def confirm(self, confirm_content):
        self.confirm_box = QMessageBox()
        self.confirm_box.setWindowTitle("请确认")
        self.confirm_box.setWindowIcon(QIcon(self.window_icon))
        self.confirm_box.setText(confirm_content)
        self.confirm_box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
        return self.confirm_box.exec()

    def add_log(self, result):
        current_time = time.strftime("%Y-%m-%d %H:%H:%S", time.localtime())
        if self.log_lines > 120:
            self.log_lines = 0
            self.log.clear()
        if result['code'] == 0:
            msg = f"{current_time}  {result['msg']}"
        else:
            msg = f"{current_time}  错误：{result['msg']}原因：{result['data']['stderr']}"
        self.log_lines += 1
        self.log.append(msg)

    def update_game_func(self):
        self.update_game.setEnabled(False)
        reply_content = "更新游戏，帕鲁游戏服务会重启一次，正在游戏的玩家将会退出，请确认是否执行！"
        reply = self.confirm(reply_content)
        if reply == QMessageBox.StandardButton.Yes:
            update_game = ServiceController(self.steamcmd_path.text())
            update_game.exec_func = [update_game.kill_pal_server,
                                     update_game.update_games, update_game.start_pal_server]
            self.update_game_thread = ControllerThread(update_game)
            self.update_game_thread.result.connect(self.add_log)
            self.update_game_thread.finished.connect(lambda: enable_button(self.update_game))
            self.update_game_thread.start()
        else:
            self.update_game.setEnabled(True)


    def recovery_archive_func(self):
        self.recovery_archive.setEnabled(False)
        reply_content = "恢复存档会覆盖原来的存档，并且帕鲁游戏服务会重启一次，正在游戏的玩家将会退出，请确认是否执行！"
        reply = self.confirm(reply_content)
        if reply == QMessageBox.StandardButton.Yes:
            select_item = self.select_archive.currentText()
            if "选择需要恢复的存档" not in select_item:
                archive_path = select_item.split(">")[0]
                recovery_archive = ServiceController(self.steamcmd_path.text())
                recovery_archive.exec_func = [recovery_archive.kill_pal_server,
                                              lambda: recovery_archive.recovery_archive(archive_path), recovery_archive.start_pal_server]
                self.recovery_archive_thread = ControllerThread(recovery_archive)
                self.recovery_archive_thread.result.connect(self.add_log)
                self.recovery_archive_thread.finished.connect(lambda: enable_button(self.recovery_archive))
                self.recovery_archive_thread.start()
            else:
                self.add_log(build_result(4, {
                    "stderr": "请选择需要恢复的存档！"
                }, msg="请选择需要恢复的存档！"))
        else:
            self.recovery_archive.setEnabled(True)

    def start_service_func(self):
        self.start_service.setEnabled(False)
        reply_content = "即将启动游戏服务，请确认是否执行！"
        reply = self.confirm(reply_content)
        if reply == QMessageBox.StandardButton.Yes:
            start = ServiceController(self.steamcmd_path.text())
            start.exec_func = start.start_pal_server
            self.start_thread = ControllerThread(start)
            self.start_thread.result.connect(self.add_log)
            self.start_thread.finished.connect(lambda: enable_button(self.start_service))
            self.start_thread.start()
        else:
            self.start_service.setEnabled(True)

    def kill_service_func(self):
        self.stop_service.setEnabled(False)
        reply_content = "即将停止游戏服务，正在游戏的玩家将会退出，请确认是否执行！"
        reply = self.confirm(reply_content)
        if reply == QMessageBox.StandardButton.Yes:
            stop = ServiceController(self.steamcmd_path.text())
            stop.exec_func = stop.kill_pal_server
            self.kill_thread = ControllerThread(stop)
            self.kill_thread.result.connect(self.add_log)
            self.kill_thread.finished.connect(lambda: enable_button(self.stop_service))
            self.kill_thread.start()
        else:
            self.stop_service.setEnabled(True)

    def update_config_func(self):
        self.start_config.setEnabled(False)
        reply_content = "一键更新配置会覆盖原来的配置，并且帕鲁游戏服务会重启一次，正在游戏的玩家将会退出，请确认是否执行！"
        reply = self.confirm(reply_content)
        if reply == QMessageBox.StandardButton.Yes:
            start = ServiceController(self.steamcmd_path.text())
            start.exec_func = [start.kill_pal_server, lambda: start.update_pal_config(
                self.pal_config_content.toPlainText()), start.start_pal_server]
            self.update_config_thread = ControllerThread(start)
            self.update_config_thread.result.connect(self.add_log)
            self.update_config_thread.finished.connect(lambda: enable_button(self.start_config))
            self.update_config_thread.start()
        else:
            self.start_config.setEnabled(True)

    def update_pal_server_status(self):
        update = ServiceController(self.steamcmd_path_select.text())
        status = update.check_pal_server()
        if len(status) == 0:
            self.pal_server_status.setText("服务运行状态：未运行")
        else:
            self.pal_server_status.setText("服务运行状态：运行中")

    def update_backup_items(self):
        try:
            self.select_archive.clear()
            self.select_archive.addItem("选择需要恢复的存档")
            zero_path = (f"{self.steamcmd_path.text()}"
                            f"/steamapps/common/PalServer/Pal/Saved/SaveGames/0")
            random_path = os.listdir(zero_path)
            for i in random_path:
                backup_path = f"{zero_path}/{i}/backup/world"
                backup_list = os.listdir(backup_path)
                for j in backup_list:
                    backup_dir = f"{backup_path}/{j}"
                    backup_size = get_dir_size(backup_dir)
                    if backup_size > 1048576:
                        size = f"{round(backup_size / 1024 / 1024, 2)}MB"
                    else:
                        size = f"{round(backup_size / 1024, 2)}KB"
                    self.select_archive.addItem(f"{i}/backup/world/{j}>存档大小：{size}")
                    if backup_dir not in self.archive_backup_path:
                        self.archive_backup_path.append(backup_dir)
        except FileNotFoundError as e:
            self.add_log(build_result(0, msg=str(e)))
        except Exception as e:
            self.add_log(build_result(0, msg=str(e)))

    def get_items(self, pattern):
        regexp = QRegularExpression(rf"{pattern}")
        result = [obj for obj in self.main_window.findChildren(QLineEdit) if regexp.match(obj.objectName()).hasMatch()]
        if not result:
            result = [obj for obj in self.main_window.findChildren(QComboBox) if regexp.match(obj.objectName()).hasMatch()]
        return result
        # self.check_items_exists()

    def check_items_exists(self):
        if self.global_pal_dict:
            for i in self.global_pal_dict.keys():
                objs = self.get_items(i)
                if objs:
                    obj = objs[0]
                    self.items_events.append(obj)
                    if isinstance(obj, QLineEdit):
                        obj.textChanged.connect(lambda: self.update_items(obj))
                        print(f"self.{obj.objectName()}.textChanged.connect(lambda: self.update_items(self.{obj.objectName()}))")
                    elif isinstance(obj, QComboBox):
                        obj.currentTextChanged.connect(lambda: self.update_items(obj))
                        print(f"self.{obj.objectName()}.currentTextChanged.connect(lambda: self.update_items(self.{obj.objectName()}))")
                else:
                    print(f"{i}未找到对象")

    def update_items(self, obj):
        if isinstance(obj, QLineEdit):
            self.global_pal_dict[obj.objectName()] = obj.text()
        elif isinstance(obj, QComboBox):
            self.global_pal_dict[obj.objectName()] = obj.currentText()
        update_dict = build_config(self.global_pal_dict)
        self.pal_config_content.setText(update_dict)

    def save_tools_config(self, data: dict):
        json_data = json.dumps(data)
        with open(self.tools_config_path, "w") as f:
            f.write(json_data)

    def init_data(self):
        self.version.setText(f"v{self.app_version}")
        if os.path.exists(self.tools_config_path):
            with open(self.tools_config_path, "r") as f:
                tools_config = json.loads(f.read())
                for i in tools_config.keys():
                    regexp = QRegularExpression(rf"{i}")
                    obj = [obj for obj in self.main_window.findChildren(QLineEdit)
                           if regexp.match(obj.objectName()).hasMatch()]
                    obj[0].setText(tools_config[i])
        try:
            service = ServiceController(self.steamcmd_path.text())
            service.exec_func = service.init_config_template
            self.init_thread = ControllerThread(service)
            self.init_thread.result.connect(self.init_data_callback)
            self.init_thread.finished.connect(self.init_data2ui)
            self.init_thread.start()
        except Exception as e:
            QMessageBox.information(self.main_window, "软件异常", f"{e}")

    def steamcmd_path_select_func(self):
        tools_config = dict()
        steamcmd_path = QFileDialog.getExistingDirectory(caption="选择文件夹")
        tools_config[self.steamcmd_path.objectName()] = steamcmd_path
        if steamcmd_path:
            self.save_tools_config(tools_config)
            self.steamcmd_path.setText(steamcmd_path)
            self.init_data()

    def init_data_callback(self, data: dict):
        self.data = data

    def init_data2ui(self):
        if "code" not in self.data.keys():
            QMessageBox.information(self.main_window, "错误", "获取配置模板失败！程序退出，请联系作者恢复~")
            QCoreApplication.quit()
            return
        self.global_pal_dict = self.data["data"]
        config_data = build_config(self.global_pal_dict)
        self.pal_config_content.setText(config_data)
        if self.data["code"] == 0:
            for i in self.global_pal_dict.keys():
                obj = self.get_items(rf"^{i}$")
                if obj:
                    if isinstance(obj[0], QLineEdit):
                        self.control_map[i] = obj[0]
                        str_type = check_string_type(self.global_pal_dict[i])
                        if str_type == 0 or str_type == 2:
                            obj[0].setText(self.global_pal_dict[i])
                        else:
                            obj[0].setText(str(round(float(self.global_pal_dict[i]), 2)))
                        obj[0].setCursorPosition(0)
                    elif isinstance(obj[0], QComboBox):
                        self.control_map[i] = obj[0]
                        obj[0].setCurrentText(self.global_pal_dict[i])
        elif self.data["code"] == 1:
            QMessageBox.information(self.main_window, "警告", self.data["msg"])
        elif self.data["code"] == 2:
            QMessageBox.information(self.main_window, "警告", self.data["msg"])
        else:
            QMessageBox.information(self.main_window, "错误", "获取配置模板失败！程序退出，请联系作者恢复~")
            QCoreApplication.quit()
            return
        self.bind_items()

    def set_default_state(self):
        obj_list = self.main_window.findChildren(QLabel)
        for i in obj_list:
            if i.objectName() not in self.only_read_items:
                i.setStyleSheet("color: black;")
                font = QFont()
                font.setBold(False)
                i.setFont(font)

    def set_highlight_state(self, obj_list):
        for i in obj_list:
            if i.objectName() not in self.only_read_items:
                i.setStyleSheet("color: red;")
                font = QFont()
                font.setBold(True)
                i.setFont(font)

    def config_search_func(self):
        self.set_default_state()
        search_value = self.config_search.text()
        if search_value == "":
            return
        if "按名称" in self.config_search_label.currentText():
            regexp = QRegularExpression(rf".*{search_value}.*")
            obj_list = [button for button in self.main_window.findChildren(QLabel)
                        if regexp.match(button.text()).hasMatch()]
        else:
            regexp = QRegularExpression(rf"^{search_value}_label$")
            obj_list = [button for button in self.main_window.findChildren(QLabel)
                        if regexp.match(button.objectName()).hasMatch()]
        self.set_highlight_state(obj_list)

    def bind_items(self):
        self.AdminPassword.textChanged.connect(lambda: self.update_items(self.AdminPassword))
        self.AllowConnectPlatform.textChanged.connect(lambda: self.update_items(self.AllowConnectPlatform))
        self.AutoResetGuildTimeNoOnlinePlayers.textChanged.connect(
            lambda: self.update_items(self.AutoResetGuildTimeNoOnlinePlayers))
        self.AutoSaveSpan.textChanged.connect(lambda: self.update_items(self.AutoSaveSpan))
        self.BanListURL.textChanged.connect(lambda: self.update_items(self.BanListURL))
        self.BaseCampMaxNumInGuild.textChanged.connect(lambda: self.update_items(self.BaseCampMaxNumInGuild))
        self.BaseCampWorkerMaxNum.textChanged.connect(lambda: self.update_items(self.BaseCampWorkerMaxNum))
        self.BuildObjectDamageRate.textChanged.connect(lambda: self.update_items(self.BuildObjectDamageRate))
        self.BuildObjectDeteriorationDamageRate.textChanged.connect(
            lambda: self.update_items(self.BuildObjectDeteriorationDamageRate))
        self.BuildObjectHpRate.textChanged.connect(lambda: self.update_items(self.BuildObjectHpRate))
        self.ChatPostLimitPerMinute.textChanged.connect(lambda: self.update_items(self.ChatPostLimitPerMinute))
        self.CollectionDropRate.textChanged.connect(lambda: self.update_items(self.CollectionDropRate))
        self.CollectionObjectHpRate.textChanged.connect(lambda: self.update_items(self.CollectionObjectHpRate))
        self.CollectionObjectRespawnSpeedRate.textChanged.connect(
            lambda: self.update_items(self.CollectionObjectRespawnSpeedRate))
        self.CoopPlayerMaxNum.textChanged.connect(lambda: self.update_items(self.CoopPlayerMaxNum))
        self.DayTimeSpeedRate.textChanged.connect(lambda: self.update_items(self.DayTimeSpeedRate))
        self.DeathPenalty.currentTextChanged.connect(lambda: self.update_items(self.DeathPenalty))
        self.Difficulty.currentTextChanged.connect(lambda: self.update_items(self.Difficulty))
        self.DropItemAliveMaxHours.textChanged.connect(lambda: self.update_items(self.DropItemAliveMaxHours))
        self.DropItemMaxNum_UNKO.textChanged.connect(lambda: self.update_items(self.DropItemMaxNum_UNKO))
        self.DropItemMaxNum.textChanged.connect(lambda: self.update_items(self.DropItemMaxNum))
        self.EnablePredatorBossPal.currentTextChanged.connect(lambda: self.update_items(self.EnablePredatorBossPal))
        self.EnemyDropItemRate.textChanged.connect(lambda: self.update_items(self.EnemyDropItemRate))
        self.ExpRate.textChanged.connect(lambda: self.update_items(self.ExpRate))
        self.GuildPlayerMaxNum.textChanged.connect(lambda: self.update_items(self.GuildPlayerMaxNum))
        self.ItemWeightRate.textChanged.connect(lambda: self.update_items(self.ItemWeightRate))
        self.LogFormatType.textChanged.connect(lambda: self.update_items(self.LogFormatType))
        self.MaxBuildingLimitNum.textChanged.connect(lambda: self.update_items(self.MaxBuildingLimitNum))
        self.NightTimeSpeedRate.textChanged.connect(lambda: self.update_items(self.NightTimeSpeedRate))
        self.PalAutoHPRegeneRate.textChanged.connect(lambda: self.update_items(self.PalAutoHPRegeneRate))
        self.PalAutoHpRegeneRateInSleep.textChanged.connect(lambda: self.update_items(self.PalAutoHpRegeneRateInSleep))
        self.PalCaptureRate.textChanged.connect(lambda: self.update_items(self.PalCaptureRate))
        self.PalDamageRateAttack.textChanged.connect(lambda: self.update_items(self.PalDamageRateAttack))
        self.PalDamageRateDefense.textChanged.connect(lambda: self.update_items(self.PalDamageRateDefense))
        self.PalEggDefaultHatchingTime.textChanged.connect(lambda: self.update_items(self.PalEggDefaultHatchingTime))
        self.PalSpawnNumRate.textChanged.connect(lambda: self.update_items(self.PalSpawnNumRate))
        self.PalStaminaDecreaceRate.textChanged.connect(lambda: self.update_items(self.PalStaminaDecreaceRate))
        self.PalStomachDecreaceRate.textChanged.connect(lambda: self.update_items(self.PalStomachDecreaceRate))
        self.PlayerAutoHPRegeneRate.textChanged.connect(lambda: self.update_items(self.PlayerAutoHPRegeneRate))
        self.PlayerAutoHpRegeneRateInSleep.textChanged.connect(
            lambda: self.update_items(self.PlayerAutoHpRegeneRateInSleep))
        self.PlayerDamageRateAttack.textChanged.connect(lambda: self.update_items(self.PlayerDamageRateAttack))
        self.PlayerDamageRateDefense.textChanged.connect(lambda: self.update_items(self.PlayerDamageRateDefense))
        self.PlayerStaminaDecreaceRate.textChanged.connect(lambda: self.update_items(self.PlayerStaminaDecreaceRate))
        self.PlayerStomachDecreaceRate.textChanged.connect(lambda: self.update_items(self.PlayerStomachDecreaceRate))
        self.PublicIP.textChanged.connect(lambda: self.update_items(self.PublicIP))
        self.PublicPort.textChanged.connect(lambda: self.update_items(self.PublicPort))
        self.RCONEnabled.currentTextChanged.connect(lambda: self.update_items(self.RCONEnabled))
        self.RCONPort.textChanged.connect(lambda: self.update_items(self.RCONPort))
        self.RESTAPIEnabled.currentTextChanged.connect(lambda: self.update_items(self.RESTAPIEnabled))
        self.RESTAPIPort.textChanged.connect(lambda: self.update_items(self.RESTAPIPort))
        self.RandomizerSeed.textChanged.connect(lambda: self.update_items(self.RandomizerSeed))
        self.RandomizerType.currentTextChanged.connect(lambda: self.update_items(self.RandomizerType))
        self.Region.textChanged.connect(lambda: self.update_items(self.Region))
        self.ServerDescription.textChanged.connect(lambda: self.update_items(self.ServerDescription))
        self.ServerName.textChanged.connect(lambda: self.update_items(self.ServerName))
        self.ServerPassword.textChanged.connect(lambda: self.update_items(self.ServerPassword))
        self.ServerPlayerMaxNum.textChanged.connect(lambda: self.update_items(self.ServerPlayerMaxNum))
        self.ServerReplicatePawnCullDistance.textChanged.connect(
            lambda: self.update_items(self.ServerReplicatePawnCullDistance))
        self.SupplyDropSpan.textChanged.connect(lambda: self.update_items(self.SupplyDropSpan))
        self.WorkSpeedRate.textChanged.connect(lambda: self.update_items(self.WorkSpeedRate))
        self.bActiveUNKO.currentTextChanged.connect(lambda: self.update_items(self.bActiveUNKO))
        self.bAutoResetGuildNoOnlinePlayers.currentTextChanged.connect(
            lambda: self.update_items(self.bAutoResetGuildNoOnlinePlayers))
        self.bBuildAreaLimit.currentTextChanged.connect(lambda: self.update_items(self.bBuildAreaLimit))
        self.bCanPickupOtherGuildDeathPenaltyDrop.currentTextChanged.connect(
            lambda: self.update_items(self.bCanPickupOtherGuildDeathPenaltyDrop))
        self.bEnableAimAssistKeyboard.currentTextChanged.connect(
            lambda: self.update_items(self.bEnableAimAssistKeyboard))
        self.bEnableAimAssistPad.currentTextChanged.connect(lambda: self.update_items(self.bEnableAimAssistPad))
        self.bEnableDefenseOtherGuildPlayer.currentTextChanged.connect(
            lambda: self.update_items(self.bEnableDefenseOtherGuildPlayer))
        self.bEnableFastTravel.currentTextChanged.connect(lambda: self.update_items(self.bEnableFastTravel))
        self.bEnableFriendlyFire.currentTextChanged.connect(lambda: self.update_items(self.bEnableFriendlyFire))
        self.bEnableInvaderEnemy.currentTextChanged.connect(lambda: self.update_items(self.bEnableInvaderEnemy))
        self.bEnableNonLoginPenalty.currentTextChanged.connect(lambda: self.update_items(self.bEnableNonLoginPenalty))
        self.bEnablePlayerToPlayerDamage.currentTextChanged.connect(
            lambda: self.update_items(self.bEnablePlayerToPlayerDamage))
        self.bExistPlayerAfterLogout.currentTextChanged.connect(lambda: self.update_items(self.bExistPlayerAfterLogout))
        self.bHardcore.currentTextChanged.connect(lambda: self.update_items(self.bHardcore))
        self.bInvisibleOtherGuildBaseCampAreaFX.currentTextChanged.connect(
            lambda: self.update_items(self.bInvisibleOtherGuildBaseCampAreaFX))
        self.bIsMultiplay.currentTextChanged.connect(lambda: self.update_items(self.bIsMultiplay))
        self.bIsPvP.currentTextChanged.connect(lambda: self.update_items(self.bIsPvP))
        self.bIsStartLocationSelectByMap.currentTextChanged.connect(
            lambda: self.update_items(self.bIsStartLocationSelectByMap))
        self.bIsUseBackupSaveData.currentTextChanged.connect(lambda: self.update_items(self.bIsUseBackupSaveData))
        self.bPalLost.currentTextChanged.connect(lambda: self.update_items(self.bPalLost))
        self.bShowPlayerList.currentTextChanged.connect(lambda: self.update_items(self.bShowPlayerList))
        self.bUseAuth.currentTextChanged.connect(lambda: self.update_items(self.bUseAuth))
        self.config_search_label.currentTextChanged.connect(self.config_search_func)


if __name__ == "__main__":
    get_admin()
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    window = PalToolsGUI(MainWindow)
    MainWindow.show()
    sys.exit(app.exec())
